Data Mining Versuch Fahrzeugdaten¶

Autor: Prof. Dr. Johannes Maucher

Dozenten:

  • Manuel Eberhardinger
  • Florian Rupp

Studierende:

  • Paul Michels (pm080)
  • Erzan Gashi (eg053)
  • Patryk Gadziomski (pg058)

Abgabe:¶

  • Abzugeben ist das Jupyter Notebook mit dem verlangten Implementierungen und den entsprechenden Ausgaben.
  • Das Notebook ist als .ipynb und als .html abzugeben.
  • Klausurelevante Fragen sind Dokument "Fragenkatalog Datamining" zu finden.
  • Antworten auf Fragen im Notebook, Diskussionen und Beschreibung der Ergebnisse sind optional (aber empfohlen) und werden nicht bewertet.
  • Übersicht Data Mining Praktikum

Einführung¶

Lernziele:¶

In diesem Versuch sollen Kenntnisse in folgenden Themen vermittelt werden:

  • Datenimport und Datenexport von und zu
    • Pandas Dataframes
    • PostgreSQL Datenbanken
  • Explorative Datenanalysen (EDA)
  • Datenvisualisierung mit Matplotlib und plotly
  • Überwachtes Lernen eines Klassifikationsmodells
  • Überwachtes Lernen eines Regressionsmodells
  • Evaluation von Klassifikationsmodellen
  • Evaluation von Regressionsmodellen
  • Kreuzvalidierung
  • Hyperparameteroptimierung

Vorbereitung¶

Datenbankzugriff¶

  1. Installieren Sie PostgreSQL. Mit PostgreSQL sollte auch pgAdmin installiert werden. PgAdmin ist eine open-source Software für die Entwicklung und die Administration von PostgreSQL Datenbanken.
  2. Legen Sie über pgAdmin eine Datenbank für das Datamining-Praktikum an. In diese Datenbank werden alle in diesem Versuch relevanten Tabellen geschrieben.
  3. Für den Datenbankzugriff aus Python heraus wird in diesem Versuch SQLAlchemy eingesetzt. Machen Sie sich mit den Basics von SQLAlchemy vertraut, z.B. mithilfe von https://maucher.pages.mi.hdm-stuttgart.de/python4datascience/07DataBaseSQL.html#using-sqlalchemy-and-pandas, Abschnitt Using SQLAlchemy and Pandas.

Pandas Dataframe¶

Machen Sie sich mit den Grundlagen von Pandas vertraut.

Machine Learning¶

Machen Sie sich mit Entscheidungsbäumen, Random Forest, Single Layer Perzeptron und Multi Layer Perzeptron vertraut.

Durchführung¶

Einlesen der Daten aus .csv und Ablage in PostgreSQL¶

In diesem ersten Teil des Versuchs sollen die relevanten Daten aus dem .csv-File eingelesen und in einer PostgreSQL-Tabelle abgelegt werden. Das benötigte File Fahrzeuginformationen.csv liegt im aktuellen Verzeichnis.

In [1]:
#conda install -y psycopg2
#!conda install -y -c anaconda sqlalchemy
In [2]:
import pandas as pd
from pandas.api.types import is_numeric_dtype
import numpy as np

from sqlalchemy import create_engine, inspect

from sklearn.preprocessing import LabelBinarizer
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import classification_report, confusion_matrix, ConfusionMatrixDisplay
from sklearn.model_selection import cross_val_score
from sklearn.ensemble import RandomForestClassifier
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import mean_squared_error, mean_absolute_error, median_absolute_error, r2_score
from sklearn.linear_model import SGDRegressor
from sklearn.neural_network import MLPRegressor
# from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import RandomizedSearchCV

import matplotlib.pyplot as plt
import seaborn as sns
import plotly.express as px

import plotly.io as pio
In [3]:
# DIese Einstellung behept der Fehler, dass der plotly express scatter plot nicht in der HTML angezeigt wurde
pio.renderers.default='notebook'
In [4]:
# Diese EINstellung erlaubt uns alle Spalten eines pandas Dataframes auszugeben
pd.set_option('display.max_columns', None)
  1. Laden Sie die .csv-Datei in einen Pandas Dataframe.
In [5]:
df = pd.read_csv("./Fahrzeuginformationen.csv")
  1. Zeigen Sie für den angelegten Dataframe
    • die ersten 10 Zeilen
In [6]:
df[:10]
Out[6]:
HST Benennung HT Benennung UT Benennung Karosserie Neupreis Brutto Produktgruppe Kraftstoffart Schadstoffklasse CCM KW HST PS Getriebeart Getriebe Benennung Anzahl der Türen Leergewicht Zuladung Zulässiges GG Länge Breite Höhe CO2-Emissionen Min Energieeffizienzklasse Antrieb KSTA Motor HST-HT Benennung
0 Volkswagen T6 Bus (SG)(05.2015->) Multivan Trendline Bs 37962 T5-Klasse Pkw BS E6 1896 112 154 Schaltgetriebe Getriebe 6-Gang 4 2211 905 2967.615635 4852 1849 2019 218 D FA STANDARD ->B Volkswagen-T6 Bus (SG)(05.2015->)
1 Volkswagen T6 Bus (SG)(05.2015->) Multivan Comfortline Bs 45294 T5-Klasse Pkw BS E6 1990 110 148 Schaltgetriebe Getriebe 6-Gang 4 2243 753 3061.848723 4859 1827 1938 218 D FA STANDARD ->B Volkswagen-T6 Bus (SG)(05.2015->)
2 Volkswagen T6 Bus (SG)(05.2015->) Multivan Generation Six Bs 48675 T5-Klasse Pkw BS E6 1943 110 150 Schaltgetriebe Getriebe 6-Gang 4 2282 768 3018.887414 4788 1823 1990 218 D FA STANDARD ->B Volkswagen-T6 Bus (SG)(05.2015->)
3 Volkswagen T6 Bus (SG)(05.2015->) Multivan 70 Jahre Bulli Bs 47201 T5-Klasse Pkw BS E6 2013 110 153 Schaltgetriebe Getriebe 6-Gang 4 1954 1007 3096.198902 4927 1952 1935 210 D FA STANDARD ->B Volkswagen-T6 Bus (SG)(05.2015->)
4 Volkswagen T6 Bus (SG)(05.2015->) Multivan Join Bs 49453 T5-Klasse Pkw BS E6 1945 112 152 Schaltgetriebe Getriebe 6-Gang 4 1984 972 3068.590854 4916 1872 2026 210 D FA STANDARD ->B Volkswagen-T6 Bus (SG)(05.2015->)
5 Volkswagen T6 Bus (SG)(05.2015->) Multivan PanAmericana Bs 50795 T5-Klasse Pkw BS E6 1938 109 154 Schaltgetriebe Getriebe 6-Gang 4 2266 823 3046.890761 4886 1895 1933 210 D FA STANDARD ->B Volkswagen-T6 Bus (SG)(05.2015->)
6 Volkswagen T6 Bus (SG)(05.2015->) Multivan Edition Bs 51605 T5-Klasse Pkw BS E6 1956 111 152 Schaltgetriebe Getriebe 6-Gang 4 2165 724 2957.083511 4658 1946 1954 210 D FA STANDARD ->B Volkswagen-T6 Bus (SG)(05.2015->)
7 Volkswagen T6 Bus (SG)(05.2015->) Multivan Join lang Bs 54560 T5-Klasse Pkw BS E6 1946 110 155 Schaltgetriebe Getriebe 6-Gang 4 2127 960 3099.520813 5162 1883 2000 212 D FA STANDARD ->B Volkswagen-T6 Bus (SG)(05.2015->)
8 Volkswagen T6 Bus (SG)(05.2015->) Multivan Highline Bs 57729 T5-Klasse Pkw BS E6 1966 106 154 Schaltgetriebe Getriebe 6-Gang 4 2317 707 3033.083391 4994 1871 1980 218 D FA STANDARD ->B Volkswagen-T6 Bus (SG)(05.2015->)
9 Volkswagen T6 Bus (SG)(05.2015->) Multivan Business Bs 97850 T5-Klasse Pkw BS E6 2029 106 152 Schaltgetriebe Getriebe 6-Gang 4 2362 605 3006.976797 4948 1900 1931 218 D FA STANDARD ->B Volkswagen-T6 Bus (SG)(05.2015->)
  • die Größe (Anzahl Zeilen und Anzahl Spalten)
In [7]:
print(f'Rows: {df.shape[0]}; Columns: {df.shape[1]}')
Rows: 24194; Columns: 25
  • die Anzahl der NaNs pro Spalte
    an.
In [8]:
df.isna().sum()
Out[8]:
HST Benennung                 0
HT Benennung                  0
UT Benennung                  0
Karosserie                    0
Neupreis Brutto               0
Produktgruppe                 0
Kraftstoffart                 0
Schadstoffklasse              0
CCM                           0
KW                            0
HST PS                        0
Getriebeart                   0
Getriebe Benennung            0
Anzahl der Türen              0
Leergewicht                   0
Zuladung                      0
Zulässiges GG                 0
Länge                         0
Breite                        0
Höhe                          0
CO2-Emissionen                0
Min Energieeffizienzklasse    0
Antrieb                       0
KSTA Motor                    0
HST-HT Benennung              0
dtype: int64
  1. Zeigen Sie mit der Pandas-Dataframe Methode info(), den Datentyp aller Spalten an. Der Typ der Spalte CO2-Emissionen ist tatsächlich kein numerischer Typ. Finden Sie heraus warum das so ist. Beheben Sie den Fehler und sorgen Sie dafür, dass auch diese Spalte einen numerischen Typ hat.
In [9]:
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 24194 entries, 0 to 24193
Data columns (total 25 columns):
 #   Column                      Non-Null Count  Dtype  
---  ------                      --------------  -----  
 0   HST Benennung               24194 non-null  object 
 1   HT Benennung                24194 non-null  object 
 2   UT Benennung                24194 non-null  object 
 3   Karosserie                  24194 non-null  object 
 4   Neupreis Brutto             24194 non-null  int64  
 5   Produktgruppe               24194 non-null  object 
 6   Kraftstoffart               24194 non-null  object 
 7   Schadstoffklasse            24194 non-null  object 
 8   CCM                         24194 non-null  int64  
 9   KW                          24194 non-null  int64  
 10  HST PS                      24194 non-null  int64  
 11  Getriebeart                 24194 non-null  object 
 12  Getriebe Benennung          24194 non-null  object 
 13  Anzahl der Türen            24194 non-null  int64  
 14  Leergewicht                 24194 non-null  int64  
 15  Zuladung                    24194 non-null  int64  
 16  Zulässiges GG               24194 non-null  float64
 17  Länge                       24194 non-null  int64  
 18  Breite                      24194 non-null  int64  
 19  Höhe                        24194 non-null  int64  
 20  CO2-Emissionen              24194 non-null  object 
 21  Min Energieeffizienzklasse  24194 non-null  object 
 22  Antrieb                     24194 non-null  object 
 23  KSTA Motor                  24194 non-null  object 
 24  HST-HT Benennung            24194 non-null  object 
dtypes: float64(1), int64(10), object(14)
memory usage: 4.6+ MB

Antwort:
Mit df['CO2-Emissionen'].astype(float) und pd.to_numeric(df['CO2-Emissionen']) wurde probiert die Werte der CO2-Emissionen als numerische Werte umzuwandeln, was in einer Fehlermedlung endete.
Die Werte der Spalte CO2-Emissionen werden als Typ object erkannt und lassen sich nicht in einen numerischen Wert umwandeln.
Wieso? : Manche der Werte sind als float-Werte gespeichert, jedoch mit einem Komma (,), was in Python nicht üblich ist. In Python werden float-Werte immer mit einem Punkt (.) definiert.
Lösung: Die Kommas in den Werten durch Punkte umtauschen und die Werte schlussendlich mit df['CO2-Emissionen'].astype(float) oder pd.to_numeric(df['CO2-Emissionen']) zu numerischne Werten (float) umwandeln.

In [10]:
df['CO2-Emissionen'] = [i.replace(',', '.') for i in df['CO2-Emissionen']]
In [11]:
df['CO2-Emissionen'] = pd.to_numeric(df['CO2-Emissionen'])

# OR df['CO2-Emissionen'] = df['CO2-Emissionen'].astype(float)
In [12]:
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 24194 entries, 0 to 24193
Data columns (total 25 columns):
 #   Column                      Non-Null Count  Dtype  
---  ------                      --------------  -----  
 0   HST Benennung               24194 non-null  object 
 1   HT Benennung                24194 non-null  object 
 2   UT Benennung                24194 non-null  object 
 3   Karosserie                  24194 non-null  object 
 4   Neupreis Brutto             24194 non-null  int64  
 5   Produktgruppe               24194 non-null  object 
 6   Kraftstoffart               24194 non-null  object 
 7   Schadstoffklasse            24194 non-null  object 
 8   CCM                         24194 non-null  int64  
 9   KW                          24194 non-null  int64  
 10  HST PS                      24194 non-null  int64  
 11  Getriebeart                 24194 non-null  object 
 12  Getriebe Benennung          24194 non-null  object 
 13  Anzahl der Türen            24194 non-null  int64  
 14  Leergewicht                 24194 non-null  int64  
 15  Zuladung                    24194 non-null  int64  
 16  Zulässiges GG               24194 non-null  float64
 17  Länge                       24194 non-null  int64  
 18  Breite                      24194 non-null  int64  
 19  Höhe                        24194 non-null  int64  
 20  CO2-Emissionen              24194 non-null  float64
 21  Min Energieeffizienzklasse  24194 non-null  object 
 22  Antrieb                     24194 non-null  object 
 23  KSTA Motor                  24194 non-null  object 
 24  HST-HT Benennung            24194 non-null  object 
dtypes: float64(2), int64(10), object(13)
memory usage: 4.6+ MB
  1. Schreiben Sie den im vorigen Schritt angepassten Dataframe mit der Pandas Methode to_sql() in eine Datenbanktabelle mit dem Namen vehicledata.
In [13]:
conn_str = 'postgresql://postgres:1234@localhost:5432/postgres'
engine = create_engine(conn_str).connect()

inspec = inspect(engine)

df.to_sql(name = 'vehicledata', con=engine, if_exists='replace')
print(inspec.has_table("vehicledata"))
True

Exemplarische Datenbankabfragen¶

  1. Verwenden Sie Pandas Dataframe Methode read_sql_query() um 3 für Sie interessante Datenbankabfragen zu implementieren. Die Resultate der Abfragen werden in einen Pandas Dataframe geschrieben. Zeigen Sie diese an.
In [14]:
abfrage_1 = pd.read_sql_query('''SELECT "Produktgruppe" FROM "vehicledata"''', engine)
abfrage_1
Out[14]:
Produktgruppe
0 T5-Klasse Pkw
1 T5-Klasse Pkw
2 T5-Klasse Pkw
3 T5-Klasse Pkw
4 T5-Klasse Pkw
... ...
24189 Van
24190 Van
24191 Van
24192 Van
24193 Van

24194 rows × 1 columns

In [15]:
abfrage_2 = pd.read_sql_query('''SELECT * FROM "vehicledata" WHERE "Produktgruppe" = 'Van' ''', engine)
abfrage_2
Out[15]:
index HST Benennung HT Benennung UT Benennung Karosserie Neupreis Brutto Produktgruppe Kraftstoffart Schadstoffklasse CCM KW HST PS Getriebeart Getriebe Benennung Anzahl der Türen Leergewicht Zuladung Zulässiges GG Länge Breite Höhe CO2-Emissionen Min Energieeffizienzklasse Antrieb KSTA Motor HST-HT Benennung
0 22112 Dacia Lodgy (04.2012->) Comfort Van 13113 Van 06 E6 1591 82 80 Schaltgetriebe Getriebe 5-Gang 5 1293 610 1785.543416 4458 1734 1726 152.0 E FA BI_LPG ->B Dacia-Lodgy (04.2012->)
1 22101 Dacia Lodgy (04.2012->) Ambiance Van 11836 Van 06 E6 1610 74 99 Schaltgetriebe Getriebe 5-Gang 5 1308 559 1757.500000 4498 1838 1691 139.0 D FA BI_LPG ->B Dacia-Lodgy (04.2012->)
2 22102 Dacia Lodgy (04.2012->) Essential Van 12027 Van 06 E6 1596 76 98 Schaltgetriebe Getriebe 5-Gang 5 1267 649 1799.967224 4520 1733 1736 139.0 D FA BI_LPG ->B Dacia-Lodgy (04.2012->)
3 22104 Dacia Lodgy (04.2012->) Laureate Van 12810 Van 06 E6 1606 73 100 Schaltgetriebe Getriebe 5-Gang 5 1279 581 1852.282920 4704 1770 1676 139.0 D FA BI_LPG ->B Dacia-Lodgy (04.2012->)
4 22105 Dacia Lodgy (04.2012->) Comfort Van 13590 Van 06 E6 1568 75 105 Schaltgetriebe Getriebe 5-Gang 5 1273 647 1835.243423 4296 1745 1696 139.0 D FA BI_LPG ->B Dacia-Lodgy (04.2012->)
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
305 24189 Ford Galaxy (CDR)(2015->) Titanium Van 48042 Van D 6T 2036 172 235 Automatikgetriebe Getriebe Automatik - Typ: 8F57 (8-Stufen) 5 1755 798 2674.077424 4756 1911 1779 158.0 B FA STANDARD ->D Ford-Galaxy (CDR)(2015->)
306 24190 Ford Galaxy (CDR)(2015->) Titanium Van 48979 Van D 6T 1974 180 241 Automatikgetriebe Getriebe Automatik - Typ: 8F57 (8-Stufen) 5 1770 775 2599.765400 4605 1977 1738 162.0 B FA STANDARD ->D Ford-Galaxy (CDR)(2015->)
307 24191 Ford S-Max (CDR)(2015->) ST-Line Van 50849 Van D 6T 2018 177 240 Automatikgetriebe Getriebe Automatik - Typ: 8F57 (8-Stufen) 5 1763 804 2546.332693 5033 2011 1592 153.0 B FA STANDARD ->D Ford-S-Max (CDR)(2015->)
308 24192 Ford S-Max (CDR)(2015->) Vignale Van 52973 Van D 6T 1968 182 238 Automatikgetriebe Getriebe Automatik - Typ: 8F57 (8-Stufen) 5 1704 820 2504.075063 4795 1941 1602 153.0 B FA STANDARD ->D Ford-S-Max (CDR)(2015->)
309 24193 Ford Galaxy (CDR)(2015->) Vignale Van 55797 Van D 6T 2019 179 239 Automatikgetriebe Getriebe Automatik - Typ: 8F57 (8-Stufen) 5 1769 821 2558.819988 5022 1865 1771 162.0 B FA STANDARD ->D Ford-Galaxy (CDR)(2015->)

310 rows × 26 columns

In [16]:
abfrage_3 = pd.read_sql_query('''SELECT "CO2-Emissionen","Produktgruppe" FROM "vehicledata" WHERE "CO2-Emissionen" = '92' ''', engine)
abfrage_3
Out[16]:
CO2-Emissionen Produktgruppe
0 92.0 Cabrio bis Kompaktklasse
1 92.0 untere Mittelklasse / Kompaktklasse
2 92.0 untere Mittelklasse / Kompaktklasse
3 92.0 untere Mittelklasse / Kompaktklasse
4 92.0 Kleinwagen
... ... ...
61 92.0 untere Mittelklasse / Kompaktklasse
62 92.0 untere Mittelklasse / Kompaktklasse
63 92.0 untere Mittelklasse / Kompaktklasse
64 92.0 untere Mittelklasse / Kompaktklasse
65 92.0 kleine SUV / Geländewagen

66 rows × 2 columns

Data Exploration¶

  1. Zeigen Sie für alle Spalten die Anzahl der unterschiedlichen Werte in dieser Spalte an.
In [17]:
df.nunique()
Out[17]:
HST Benennung                    42
HT Benennung                    617
UT Benennung                   3782
Karosserie                       22
Neupreis Brutto               19739
Produktgruppe                    28
Kraftstoffart                    14
Schadstoffklasse                  4
CCM                            2197
KW                              428
HST PS                          560
Getriebeart                       2
Getriebe Benennung              103
Anzahl der Türen                  4
Leergewicht                    1833
Zuladung                       1208
Zulässiges GG                 23919
Länge                          2342
Breite                          651
Höhe                           1203
CO2-Emissionen                  279
Min Energieeffizienzklasse        8
Antrieb                           3
KSTA Motor                        6
HST-HT Benennung                617
dtype: int64
  1. Benutzen Sie die Pandas Dataframe Methode describe() um sämtliche deskriptiven Statistiken anzuzeigen.
In [18]:
df.describe()
Out[18]:
Neupreis Brutto CCM KW HST PS Anzahl der Türen Leergewicht Zuladung Zulässiges GG Länge Breite Höhe CO2-Emissionen
count 24194.000000 24194.000000 24194.000000 24194.000000 24194.000000 24194.000000 24194.000000 24194.000000 24194.000000 24194.000000 24194.000000 24194.000000
mean 40301.051790 1851.156361 126.653798 172.273126 4.480656 1588.890303 578.716211 2134.695183 4560.681905 1835.296478 1579.427503 135.869906
std 22037.781929 616.193218 60.835718 82.667899 0.880526 367.170624 191.292064 524.077515 412.813020 93.258553 219.588359 33.439398
min 6835.000000 831.000000 42.000000 51.000000 2.000000 29.000000 58.000000 0.000000 2571.000000 1394.000000 1180.000000 8.500000
25% 26910.000000 1482.000000 88.000000 120.000000 4.000000 1381.000000 483.000000 1872.562390 4339.000000 1782.000000 1446.000000 115.000000
50% 36720.000000 1941.000000 111.000000 151.000000 5.000000 1555.000000 547.000000 2075.265444 4575.000000 1829.000000 1502.000000 130.000000
75% 47632.250000 2011.000000 141.000000 192.000000 5.000000 1745.000000 615.000000 2319.881506 4801.000000 1883.000000 1647.000000 153.000000
max 287347.000000 6706.000000 511.000000 705.000000 5.000000 10365.000000 7726.000000 15295.850636 6958.000000 2293.000000 3023.000000 397.000000
  1. Legen Sie eine Liste numeric_features an, welche nur die Spaltennamen der numerischen Spalten enthält.
In [19]:
numeric_features = [i for i in df.columns.values if is_numeric_dtype(df[i]) == True]
numeric_features
Out[19]:
['Neupreis Brutto',
 'CCM',
 'KW',
 'HST PS',
 'Anzahl der Türen',
 'Leergewicht',
 'Zuladung',
 'Zulässiges GG',
 'Länge',
 'Breite',
 'Höhe',
 'CO2-Emissionen']
  1. Schreiben Sie die Namen aller nicht-numerischen Spalten in eine Liste categoric_features.
In [20]:
categoric_features = [i for i in df.columns.values if is_numeric_dtype(df[i]) == False]
categoric_features
Out[20]:
['HST Benennung',
 'HT Benennung',
 'UT Benennung',
 'Karosserie',
 'Produktgruppe',
 'Kraftstoffart',
 'Schadstoffklasse',
 'Getriebeart',
 'Getriebe Benennung',
 'Min Energieeffizienzklasse',
 'Antrieb',
 'KSTA Motor',
 'HST-HT Benennung']
  1. Visualisieren Sie für die Spalten HST_Benennung, Neupreis Brutto, CO2-Emissionen und Produktgruppe die Verteilung der Werte in einem Barplot bzw. Histogramm.
In [21]:
df_for_plot_hst = df['HST Benennung'].value_counts()
df_for_plot_neupreis = df['Neupreis Brutto'].value_counts()
df_for_plot_co2 = df['CO2-Emissionen'].value_counts()
df_for_plot_produkt = df['Produktgruppe'].value_counts()
In [22]:
fig, axes = plt.subplots(nrows=1, ncols=2)

df_for_plot_hst.plot(ax=axes[0], kind='bar', title='HST Benennung / BAR', figsize=(15, 10))
df_for_plot_hst.plot(ax=axes[1], kind='hist', title='HST Benennung / HIST', figsize=(15, 10))

fig.set_figheight(5)
fig.set_figwidth(15)

plt.show()
No description has been provided for this image
In [23]:
fig2, axes = plt.subplots(nrows=1, ncols=2)

# Wir benutzen hier nur jeeils die ersten 100 Reihen, da der plot ansonsten zu unüberischtlich wird
# Wenn gewünscht wird alle Reihen auszugeben: "[:100]" aus den beiden unteren Zeilen entfernen
df_for_plot_neupreis[:100].plot(ax=axes[0], kind='bar', title='Neupreis Brutto / BAR', figsize=(15, 10))
df_for_plot_neupreis[:100].plot(ax=axes[1], kind='hist', title='Neupreis Brutto / HIST', figsize=(15, 10))

fig2.set_figheight(5)
fig2.set_figwidth(15)

plt.show()
No description has been provided for this image
In [24]:
fig3, axes = plt.subplots(nrows=1, ncols=2)

df_for_plot_co2.plot(ax=axes[0], kind='bar', title='CO2 Emission / BAR', figsize=(15, 10))
df_for_plot_co2.plot(ax=axes[1], kind='hist', title='CO2 Emission / HIST', figsize=(15, 10))

fig3.set_figheight(5)
fig3.set_figwidth(15)

plt.show()
No description has been provided for this image
In [25]:
fig4, axes = plt.subplots(nrows=1, ncols=2)

df_for_plot_produkt.plot(ax=axes[0], kind='bar', title='Produktgruppe / BAR', figsize=(15, 10))
df_for_plot_produkt.plot(ax=axes[1], kind='hist', title='Produktgruppe / HIST', figsize=(15, 10))

fig4.set_figheight(5)
fig4.set_figwidth(15)

plt.show()
No description has been provided for this image

Machine Learning 1: Produktgruppenbestimmung¶

In diesem Abschnitt soll ein Klassifikator trainiert werden, welcher anhand von Eingabemerkmalen, wie Breite, Höhe, Gewicht usw. das zugehörige Fahrzeugsegment (Produktgruppe) vorhersagt.

In diesem Teilversuch sollen als Eingabemerkmale die zuvor in numeric_features definierten Spalten und die nicht-numerischen Spalten Antrieb, Kraftstoffart, KSTA Motor verwendet werden. Die Zielvariable (Ausgabe) stellt die Spalte Produktgruppe dar.

Produktgrunppenspezifische Visualisierung¶

  1. Plotten Sie für die drei oben angegebenen nicht-numerischen Merkmale jeweils eine Produktgruppen-spezifische Häufigkeitsverteilung in der unten dargestellten Form.
No description has been provided for this image
In [26]:
df.groupby(['Produktgruppe', 'Antrieb']).size().unstack().plot(kind='barh', 
                                                               stacked=True, 
                                                               figsize=(10, 8), 
                                                               title='Antrieb pro Produktgruppe', 
                                                               xlabel='Anzahl')
Out[26]:
<Axes: title={'center': 'Antrieb pro Produktgruppe'}, xlabel='Anzahl', ylabel='Produktgruppe'>
No description has been provided for this image
In [27]:
df.groupby(['Produktgruppe', 'Kraftstoffart']).size().unstack().plot(kind='barh', 
                                                               stacked=True, 
                                                               figsize=(10, 8), 
                                                               title='Kraftstoffart pro Produktgruppe', 
                                                               xlabel='Anzahl')
Out[27]:
<Axes: title={'center': 'Kraftstoffart pro Produktgruppe'}, xlabel='Anzahl', ylabel='Produktgruppe'>
No description has been provided for this image
In [28]:
df.groupby(['Produktgruppe', 'KSTA Motor']).size().unstack().plot(kind='barh', 
                                                               stacked=True, 
                                                               figsize=(10, 8), 
                                                               title='KSTA Motor pro Produktgruppe', 
                                                               xlabel='Anzahl')
Out[28]:
<Axes: title={'center': 'KSTA Motor pro Produktgruppe'}, xlabel='Anzahl', ylabel='Produktgruppe'>
No description has been provided for this image
  1. Plotten Sie für alle numerischen Merkmale jeweils einen Produktgruppen-spezifischen Boxplot in der unten dargestellten Form.
No description has been provided for this image
In [29]:
sns.boxplot(x="Neupreis Brutto", 
            y='Produktgruppe', 
            data=df,
            orient='h',
            hue='Produktgruppe',
            palette='tab10').set_title('Neupreis Brutto pro Produktgruppe')
Out[29]:
Text(0.5, 1.0, 'Neupreis Brutto pro Produktgruppe')
No description has been provided for this image
In [30]:
sns.boxplot(x="CCM", 
            y='Produktgruppe', 
            data=df,
            orient='h',
            hue='Produktgruppe',
            palette='tab10').set_title('CCM pro Produktgruppe')
Out[30]:
Text(0.5, 1.0, 'CCM pro Produktgruppe')
No description has been provided for this image
In [31]:
sns.boxplot(x="KW", 
            y='Produktgruppe', 
            data=df,
            orient='h',
            hue='Produktgruppe',
            palette='tab10').set_title('KW pro Produktgruppe')
Out[31]:
Text(0.5, 1.0, 'KW pro Produktgruppe')
No description has been provided for this image
In [32]:
sns.boxplot(x="HST PS", 
            y='Produktgruppe', 
            data=df,
            orient='h',
            hue='Produktgruppe',
            palette='tab10').set_title('HST PS pro Produktgruppe')
Out[32]:
Text(0.5, 1.0, 'HST PS pro Produktgruppe')
No description has been provided for this image
In [33]:
sns.boxplot(x="Anzahl der Türen", 
            y='Produktgruppe', 
            data=df,
            orient='h',
            hue='Produktgruppe',
            palette='tab10').set_title('Anzahl der Türen pro Produktgruppe')
Out[33]:
Text(0.5, 1.0, 'Anzahl der Türen pro Produktgruppe')
No description has been provided for this image
In [34]:
sns.boxplot(x="Leergewicht", 
            y='Produktgruppe', 
            data=df,
            orient='h',
            hue='Produktgruppe',
            palette='tab10').set_title('Leergewicht pro Produktgruppe')
Out[34]:
Text(0.5, 1.0, 'Leergewicht pro Produktgruppe')
No description has been provided for this image
In [35]:
sns.boxplot(x="Zuladung", 
            y='Produktgruppe', 
            data=df,
            orient='h',
            hue='Produktgruppe',
            palette='tab10').set_title('Zuladung pro Produktgruppe')
Out[35]:
Text(0.5, 1.0, 'Zuladung pro Produktgruppe')
No description has been provided for this image
In [36]:
sns.boxplot(x="Zulässiges GG", 
            y='Produktgruppe', 
            data=df,
            orient='h',
            hue='Produktgruppe',
            palette='tab10').set_title('Zulässiges GG pro Produktgruppe')
Out[36]:
Text(0.5, 1.0, 'Zulässiges GG pro Produktgruppe')
No description has been provided for this image
In [37]:
sns.boxplot(x="Länge", 
            y='Produktgruppe', 
            data=df,
            orient='h',
            hue='Produktgruppe',
            palette='tab10').set_title('Länge pro Produktgruppe')
Out[37]:
Text(0.5, 1.0, 'Länge pro Produktgruppe')
No description has been provided for this image
In [38]:
sns.boxplot(x="Breite", 
            y='Produktgruppe', 
            data=df,
            orient='h',
            hue='Produktgruppe',
            palette='tab10').set_title('Breite pro Produktgruppe')
Out[38]:
Text(0.5, 1.0, 'Breite pro Produktgruppe')
No description has been provided for this image
In [39]:
sns.boxplot(x="Höhe", 
            y='Produktgruppe', 
            data=df,
            orient='h',
            hue='Produktgruppe',
            palette='tab10').set_title('Höhe pro Produktgruppe')
Out[39]:
Text(0.5, 1.0, 'Höhe pro Produktgruppe')
No description has been provided for this image
In [40]:
sns.boxplot(x="CO2-Emissionen", 
            y='Produktgruppe', 
            data=df,
            orient='h',
            hue='Produktgruppe',
            palette='tab10').set_title('CO2-Emissionen pro Produktgruppe')
Out[40]:
Text(0.5, 1.0, 'CO2-Emissionen pro Produktgruppe')
No description has been provided for this image
  1. Erzeugen Sie mit plotly.express scatter() einen 2-dimensionalen Plot, in dem alle Fahrzeuge wie folgt dargestellt werden (pro Fahrzeug ein Marker):
  • x-Achse: Länge
  • y-Achse: Höhe
  • Farbe des Markers: Produktgruppe
  • Größe des Markers: Leergewicht
  • Bei Mouse-Over soll für den jeweiligen Marker der entsprechende Wert von Neupreis Brutto und HST-HT Benennung angezeigt werden.
In [41]:
# Der Scatter Plot wird in der HTML nicht angezeigt. 
# Grund: Leider keine Ahnung.
# Um den Scatter Plot zu sehen, navigieren Sie in das Notebook und führen sie die Zellen bis zu dem Scatter Plot aus.

fig = px.scatter(df, 
                 x='Länge', 
                 y='Höhe', 
                 color='Produktgruppe',
                 size='Leergewicht', 
                 hover_data={'Neupreis Brutto': True, 
                             'HST-HT Benennung': True},
                title='Scatter Plot'
                )
fig.show()

Data Encoding¶

  1. Categoriale Merkmale ohne Ordnungsrelation (=nominale Merkmale) müssen One-Hot-Encodiert werden. Führen Sie für die drei categorialen Merkmale ein One-Hot-Encoding mit dem scikit-learn LabelBinarizer durch.
In [42]:
def one_hot_encoding(lb, feature):
    lb.fit(feature)
    return lb.transform(list(feature))
In [43]:
lb = LabelBinarizer()

cat_features = ['Antrieb', 'Kraftstoffart', 'KSTA Motor']

for feature in cat_features:
    cats = df[feature].value_counts().index
    sep_cats = [i.strip() for i in cats]
    cats_count = len(sep_cats)

    ohe_values = one_hot_encoding(lb=lb, feature=df[feature])

    for i in range(cats_count):
        values_list = [j[i] for j in ohe_values]
        df[f"{feature}_{sep_cats[i]}"] = values_list
  1. Fügen Sie die one-hot-encodierten Spalten mit den numerischen Spalten zusammen. Weisen Sie die entsprechende Eingabedatenmatrix einem 2-dimensionalen numpy-array X zu.
In [44]:
numeric_features = [i for i in df.columns.values if is_numeric_dtype(df[i]) == True]
X = df[numeric_features]
In [45]:
X
Out[45]:
Neupreis Brutto CCM KW HST PS Anzahl der Türen Leergewicht Zuladung Zulässiges GG Länge Breite Höhe CO2-Emissionen Antrieb_FA Antrieb_A Antrieb_HA Kraftstoffart_D Kraftstoffart_BS Kraftstoffart_08 Kraftstoffart_SP Kraftstoffart_06 Kraftstoffart_07 Kraftstoffart_E Kraftstoffart_10 Kraftstoffart_25 Kraftstoffart_09 Kraftstoffart_26 Kraftstoffart_B1 Kraftstoffart_S Kraftstoffart_BN KSTA Motor_STANDARD ->D KSTA Motor_STANDARD ->B KSTA Motor_HYBRID ->B KSTA Motor_HYBRID ->D KSTA Motor_BI_CNG ->B KSTA Motor_BI_LPG ->B
0 37962 1896 112 154 4 2211 905 2967.615635 4852 1849 2019 218.0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0
1 45294 1990 110 148 4 2243 753 3061.848723 4859 1827 1938 218.0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0
2 48675 1943 110 150 4 2282 768 3018.887414 4788 1823 1990 218.0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0
3 47201 2013 110 153 4 1954 1007 3096.198902 4927 1952 1935 210.0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0
4 49453 1945 112 152 4 1984 972 3068.590854 4916 1872 2026 210.0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
24189 48042 2036 172 235 5 1755 798 2674.077424 4756 1911 1779 158.0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1
24190 48979 1974 180 241 5 1770 775 2599.765400 4605 1977 1738 162.0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1
24191 50849 2018 177 240 5 1763 804 2546.332693 5033 2011 1592 153.0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1
24192 52973 1968 182 238 5 1704 820 2504.075063 4795 1941 1602 153.0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1
24193 55797 2019 179 239 5 1769 821 2558.819988 5022 1865 1771 162.0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1

24194 rows × 35 columns

  1. Führen Sie auf die Zielvariable Produktgruppe ein Label-Encoding mit scikit-learn LabelEncoder aus. Weisen Sie diese Daten dem 1-dimensionalen numpy-array y zu.
In [46]:
le = LabelEncoder()
le.fit(df['Produktgruppe'])
lb_produktgruppe = le.transform(df['Produktgruppe'])
y = lb_produktgruppe
In [47]:
y
Out[47]:
array([21, 21, 21, ..., 22, 22, 22])

Generate Training- and Testpartition¶

Benutzen Sie die scikit-learn Methode train_test_split() um X und y in einer Trainings- und Testpartition aufzuteilen. 30% der Daten soll für das Testen, 70% für das Training benutzt werden.

In [48]:
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
In [49]:
print(len(X))
print(len(X_train))
print(len(X_test))
print('-------------')
print(len(y))
print(len(y_train))
print(len(y_test))
24194
16935
7259
-------------
24194
16935
7259

Decision Tree Training, Test and Evaluation¶

  1. Trainieren Sie einen Entscheidungsbaum mit den Trainingsdaten.
In [50]:
clf_dt = DecisionTreeClassifier(random_state=42)
clf_dt = clf_dt.fit(X_train, y_train)
  1. Wenden Sie den gelernten Entscheidungsbaum auf die Testdaten an.
In [51]:
clf_dt.predict(X_test)
Out[51]:
array([26, 14,  8, ..., 25, 14, 27])
  1. Evaluieren Sie die Qualität des Entscheidungsbaumes indem Sie
    • einen classification_report erzeugen.
In [52]:
y_true = y_test
y_pred = clf_dt.predict(X_test)
In [53]:
print(classification_report(y_true, y_pred))
              precision    recall  f1-score   support

           0       0.79      0.82      0.80        92
           1       0.92      0.92      0.92        86
           2       0.79      0.81      0.80       117
           3       0.96      0.73      0.83        33
           4       0.81      0.88      0.84        67
           5       0.64      0.63      0.64        68
           6       0.91      0.85      0.88       468
           7       0.69      0.68      0.68       622
           8       0.68      0.70      0.69       481
           9       0.70      0.78      0.74         9
          10       0.61      0.61      0.61        18
          11       0.86      0.86      0.86       106
          12       0.51      0.49      0.50        41
          13       0.96      0.97      0.96       287
          14       0.87      0.88      0.88      1206
          15       0.89      0.85      0.87        98
          16       0.83      0.88      0.86        17
          17       0.78      0.66      0.71        70
          18       0.46      0.53      0.49        49
          19       0.99      0.98      0.99       174
          20       0.92      0.91      0.91       193
          21       0.82      0.87      0.85       211
          22       0.84      0.75      0.80        93
          23       0.90      0.90      0.90       247
          24       0.69      0.72      0.70       173
          25       0.76      0.76      0.76       584
          26       0.82      0.86      0.84       340
          27       0.86      0.85      0.86      1309

    accuracy                           0.82      7259
   macro avg       0.79      0.79      0.79      7259
weighted avg       0.82      0.82      0.82      7259

Antwort:

  • Aus der Precision lässt sich erkennen, dass ein Großteil der Produktgruppen meistes richtig erkannt wird (True-Postive). Allerdings werden Produktgruppen wie zum Beispiel der Kleinwagen, oder Kleintransporter/Pkw, öfter als False-Positive erkannt, als True-Positive.
  • Aus dem Recall lässt sich der genaue Prozentwert der Treffer herauslesen.
    • Die meisten werden tatsächlcih gut erkannt, bis auf den Pkw und den Kleinwagen
    • Die Luxuslimousine und Sprinterklasse haben wenig False-Negative
  • F1-Score ist das harmonische Mittel aus Precision und Recall und bestätigt die bisherigen Annahmen
  • die confusion matrix plotten.
In [54]:
cm = confusion_matrix(y_test, y_pred, labels=clf_dt.classes_)

disp = ConfusionMatrixDisplay(confusion_matrix=cm,
                              display_labels=clf_dt.classes_,)

fig, ax = plt.subplots(figsize=(20, 20))

disp.plot(ax=ax)

# Die Nummern auf den Axen entsprechen den Produktgruppen (labels)
Out[54]:
<sklearn.metrics._plot.confusion_matrix.ConfusionMatrixDisplay at 0x1d2babfa820>
No description has been provided for this image
  1. Interpretieren Sie das Ergebnis.

Die Diagonale ist erkennbar, was auf True-Positive Werte hindeutet. Allerdings kommen bei ähnlichen Produktgruppen False-Postiv Werte raus.

Beipsiele:

  • Der Coupé Mittelklasse und sport Coupé werden öfter als False-Postive erkannt, da diese ähnliche Bausgröße/Krafstoffverbrauch haben
  • Der LKW wird öfter mit dem Mini-Van und Van verwechselt
  1. Führen Sie eine 10-fache Kreuzvalidierung des Entscheidungsbaumes mit den Daten X und y aus. Interpretieren Sie das Ergebnis.
In [55]:
print(cross_val_score(clf_dt, X, y, cv=10))
[0.68636364 0.69380165 0.73057851 0.70454545 0.74369574 0.70442332
 0.74121538 0.77180653 0.77139314 0.74245556]

Antwort:

Die 10-fache Kreuzvalidierung erzeugt 10 Partitionen des Datensatzes und trainiert 10 Mal den Decision Tree jeweils mit den Partitionen.
Dadurch wird der trainierte Decision Tree auf unterschiedlichen Partitionen gestestet.
Da wir eine Range ~9% haben, deutete es darauf hin, dass die unterschiedlichen Produktgruppen nicht gleich häufig im Datensatz vorkommen (Vermutung anhand der Abweichung).

  1. Bestimmen Sie die Wichtigkeit der Eingabemerkmale für die Klassifikationsaufgabe, indem Sie auf den in 1.) gelernten DecisionTree das Attribut feature_importance_ abfragen. Stellen Sie die Werte in einem Barplot dar.
In [56]:
clf_dt.feature_importances_
Out[56]:
array([1.09398363e-01, 3.24803871e-02, 3.75496660e-02, 1.72638629e-02,
       7.39412156e-02, 4.02930399e-02, 6.37606257e-02, 1.61026519e-01,
       2.11923757e-01, 3.48432122e-02, 1.53880717e-01, 3.56139665e-02,
       1.07886388e-02, 6.50683425e-04, 1.03486884e-02, 1.13149140e-04,
       0.00000000e+00, 2.44709984e-05, 0.00000000e+00, 0.00000000e+00,
       0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
       1.42579649e-03, 1.18108211e-03, 0.00000000e+00, 0.00000000e+00,
       1.13176742e-04, 1.09584658e-04, 1.23565353e-04, 9.24996706e-04,
       6.52695327e-04, 8.57453503e-04, 7.10686262e-04])
In [57]:
bar_df = pd.DataFrame({
    'feature': X.columns,
    'value': clf_dt.feature_importances_
})

sns.barplot(bar_df, x="value", y="feature", orient='y').set_title('Relevanz der features')
Out[57]:
Text(0.5, 1.0, 'Relevanz der features')
No description has been provided for this image

Random Forest Training, Test and Evaluation¶

Wiederholen Sie die Teilaufgaben 1. bis 5. des Entscheidungsbaums für einen Random Forest. Vergelichen Sie die Performance der beiden Verfahren.

In [58]:
clf_rf = RandomForestClassifier(random_state=42)
clf_rf.fit(X_train, y_train)
Out[58]:
RandomForestClassifier(random_state=42)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
RandomForestClassifier(random_state=42)
In [59]:
clf_rf.predict(X_test)
Out[59]:
array([14, 14,  8, ..., 25, 14, 14])
In [60]:
y_pred = clf_rf.predict(X_test)
In [61]:
print(classification_report(y_test, y_pred))
              precision    recall  f1-score   support

           0       0.91      1.00      0.95        92
           1       0.94      0.98      0.96        86
           2       0.99      0.95      0.97       117
           3       0.97      0.97      0.97        33
           4       0.98      0.90      0.94        67
           5       0.78      0.46      0.57        68
           6       0.94      0.95      0.95       468
           7       0.88      0.82      0.85       622
           8       0.82      0.88      0.85       481
           9       0.75      0.67      0.71         9
          10       0.81      0.72      0.76        18
          11       0.93      0.94      0.93       106
          12       0.91      0.51      0.66        41
          13       0.99      1.00      0.99       287
          14       0.96      0.97      0.96      1206
          15       0.99      0.93      0.96        98
          16       1.00      1.00      1.00        17
          17       0.78      0.76      0.77        70
          18       0.61      0.51      0.56        49
          19       0.99      1.00      0.99       174
          20       0.93      0.96      0.95       193
          21       0.92      0.93      0.93       211
          22       0.95      0.88      0.92        93
          23       0.98      0.96      0.97       247
          24       0.82      0.82      0.82       173
          25       0.90      0.92      0.91       584
          26       0.96      0.95      0.96       340
          27       0.92      0.95      0.94      1309

    accuracy                           0.92      7259
   macro avg       0.90      0.87      0.88      7259
weighted avg       0.92      0.92      0.92      7259

Antwort:

Die Ergebnisse haben sich im Vergleich zum Decision Tree deutlich verbessert.
Trotz dessen gibt es kleine Ausreißer wie Kleintransporter/Pkw und Kleinwagen, welche immernoch einen schlechten Wert vorweisen.
Ähnich lässt es sich aus der Cunfusion Matrix herauslesen. Die Accuracy wurde besser, jedoch nicht perfekt.

In [62]:
cm = confusion_matrix(y_test, y_pred, labels=clf_rf.classes_)

disp = ConfusionMatrixDisplay(confusion_matrix=cm,
                              display_labels=clf_rf.classes_,)

fig, ax = plt.subplots(figsize=(20,20))

disp.plot(ax=ax)
Out[62]:
<sklearn.metrics._plot.confusion_matrix.ConfusionMatrixDisplay at 0x1d2bbee5070>
No description has been provided for this image
In [63]:
print(cross_val_score(clf_rf, X, y, cv=10))
[0.77396694 0.73677686 0.7785124  0.76322314 0.7875155  0.75196362
 0.77552708 0.81976023 0.8284415  0.77635387]

Antwort:

Die Abweichung der Werte liegt wieder bei ~9%. Die Werte sind generell höher als beim Decision Tree, dass heißt der Random Forest ist besser angepasst.

In [64]:
clf_rf.feature_importances_
Out[64]:
array([8.13880109e-02, 4.80132497e-02, 4.39856123e-02, 4.72735511e-02,
       4.96036994e-02, 9.13182928e-02, 8.33262806e-02, 1.18075542e-01,
       1.29651940e-01, 5.35136731e-02, 1.51794796e-01, 5.13812154e-02,
       8.51171399e-03, 1.05259039e-02, 9.20814812e-03, 2.62434314e-04,
       1.72253973e-04, 1.20345471e-03, 3.41593837e-05, 2.76598482e-04,
       1.41195819e-04, 1.10484515e-05, 4.04012859e-06, 0.00000000e+00,
       3.84054298e-03, 4.17056478e-03, 2.52443272e-04, 6.93397919e-07,
       9.02322194e-04, 2.73222582e-04, 2.20562070e-04, 1.66307374e-03,
       8.73149542e-04, 3.80388543e-03, 4.32272635e-03])
In [65]:
bar_df = pd.DataFrame({
    'feature': X.columns,
    'value': clf_rf.feature_importances_
})

sns.barplot(bar_df, x="value", y="feature", orient='y').set_title('Relevanz der features')
Out[65]:
Text(0.5, 1.0, 'Relevanz der features')
No description has been provided for this image

Machine Learning 2: Schätzung der CO2-Emission¶

In diesem Teilversuch soll aus den Eingabemerkmalen

"CCM","HST PS", "Anzahl der Türen", "Leergewicht", "Zuladung", "Länge", "Breite", "Höhe"

die Zielvariable

CO2-Emissionen

geschätzt werden. Hierzu soll ein möglichst gutes Regressionsmodell trainiert werden.

In [66]:
co2_df = df[["CCM", "HST PS", "Anzahl der Türen", "Leergewicht", "Zuladung", "Länge", "Breite", "Höhe", "CO2-Emissionen"]]
In [67]:
co2_df.head()
Out[67]:
CCM HST PS Anzahl der Türen Leergewicht Zuladung Länge Breite Höhe CO2-Emissionen
0 1896 154 4 2211 905 4852 1849 2019 218.0
1 1990 148 4 2243 753 4859 1827 1938 218.0
2 1943 150 4 2282 768 4788 1823 1990 218.0
3 2013 153 4 1954 1007 4927 1952 1935 210.0
4 1945 152 4 1984 972 4916 1872 2026 210.0

Visuelle Korrelationsanalyse¶

  1. Stellen Sie für jedes der 8 Eingabemerkmale die Korrelation mit der Zielvariablen visuell in einem Scatterplot dar, in dem das jeweilige Eingabemerkmal auf der x-Achse und die Zielvariable auf der y-Achse aufgetragen wird.
In [68]:
px.scatter(co2_df,
           x='CCM', 
           y='CO2-Emissionen',
           title='CCM im Vergleich zur CO2-Emissionen')
In [69]:
px.scatter(co2_df,
           x='HST PS', 
           y='CO2-Emissionen',
           title='HST PS im Vergleich zur CO2-Emissionen')
In [70]:
px.scatter(co2_df,
           x='Anzahl der Türen', 
           y='CO2-Emissionen',
           title='Anzahl der Türen im Vergleich zur CO2-Emissionen')
In [71]:
px.scatter(co2_df,
           x='Leergewicht', 
           y='CO2-Emissionen',
           title='Leergewicht im Vergleich zur CO2-Emissionen')
In [72]:
px.scatter(co2_df,
           x='Zuladung', 
           y='CO2-Emissionen',
           title='Zuladung im Vergleich zur CO2-Emissionen')
In [73]:
px.scatter(co2_df,
           x='Länge', 
           y='CO2-Emissionen',
           title='Länge im Vergleich zur CO2-Emissionen')
In [74]:
px.scatter(co2_df,
           x='Breite', 
           y='CO2-Emissionen',
           title='Breite im Vergleich zur CO2-Emissionen')
In [75]:
px.scatter(co2_df,
           x='Höhe', 
           y='CO2-Emissionen',
           title='Höhe im Vergleich zur CO2-Emissionen')
  1. Diskutieren Sie die Korrelationen. Welche Merkmale korrelieren am stärksten mit der Zielvariable? Erscheint Ihnen das plausibel?

Antwort:

  • Anzahl der Türen erscheint nutzlos
  • Am stärksten koorelieren CCM und HST PS, da diese direkt mit dem Spritverbrauch korrelieren
  • Länge und Breite korrleiren einigermaßen mit der Zielvariable, weil ein längeres und breiteres Auto in der Regel mehr wiegt und somit einen höhren Spritverbrauch haben
    • Auch in Hinsicht auf den Luftwiderstand bei der Form/Länge/Breite des Wagens

Data Encoding¶

  1. Weisen Sie die Matrix der Eingabedaten dem 2-dimensionalen Array X und die Zielvariable dem 1-dimensionalen Array y zu.
In [76]:
X2 = co2_df.iloc[:, :-1]
y2 = co2_df.iloc[:, -1:]
In [77]:
X2.head()
Out[77]:
CCM HST PS Anzahl der Türen Leergewicht Zuladung Länge Breite Höhe
0 1896 154 4 2211 905 4852 1849 2019
1 1990 148 4 2243 753 4859 1827 1938
2 1943 150 4 2282 768 4788 1823 1990
3 2013 153 4 1954 1007 4927 1952 1935
4 1945 152 4 1984 972 4916 1872 2026
In [78]:
y2.head()
Out[78]:
CO2-Emissionen
0 218.0
1 218.0
2 218.0
3 210.0
4 210.0
  1. Führen Sie auf X und y eine Partitionierung in Trainings- und Testdaten durch, wieder im Verhältnis 70/30.
In [79]:
X2_train, X2_test, y2_train, y2_test = train_test_split(X2, y2, test_size=0.3, random_state=42)
In [80]:
print(len(X2))
print(len(X2_train))
print(len(X2_test))
print('-------------')
print(len(y2))
print(len(y2_train))
print(len(y2_test))
24194
16935
7259
-------------
24194
16935
7259
  1. Skalieren Sie die Eingabevariablen und die Zielvariable mit dem MinMaxScaler. Die Skalierung muss sowohl auf Trainings- als auch auf Testdaten ausgeführt werden. Warum darf die Skalierung erst nach dem Split in die beiden Partitionen ausgeführt werden? Worauf ist zu achten?
In [81]:
scaler = MinMaxScaler()
In [82]:
scaler.fit(X2_train)
X2_train = scaler.transform(X2_train)
In [83]:
scaler.fit(X2_test)
X2_test = scaler.transform(X2_test)
In [84]:
scaler.fit(y2_train)
y2_train = scaler.transform(y2_train)
In [85]:
scaler.fit(y2_test)
y2_test = scaler.transform(y2_test)
In [86]:
X2_train
Out[86]:
array([[0.20017021, 0.14678899, 1.        , ..., 0.38978801, 0.53058954,
        0.14650027],
       [0.10978723, 0.08256881, 1.        , ..., 0.39092774, 0.46162403,
        0.15626696],
       [0.37565957, 0.28134557, 1.        , ..., 0.51766583, 0.57063404,
        0.13944655],
       ...,
       [0.06808511, 0.12538226, 0.        , ..., 0.33781628, 0.35261402,
        0.15084102],
       [0.19574468, 0.19877676, 1.        , ..., 0.38933212, 0.42714127,
        0.13347802],
       [0.18757447, 0.14678899, 1.        , ..., 0.40323684, 0.46718576,
        0.35485621]])
In [87]:
X2_test
Out[87]:
array([[0.20633227, 0.20760697, 0.66666667, ..., 0.60474205, 0.43112245,
        0.16330166],
       [0.20330843, 0.2614897 , 1.        , ..., 0.50807712, 0.40433673,
        0.1543943 ],
       [0.12628958, 0.07131537, 1.        , ..., 0.54247004, 0.56505102,
        0.40973872],
       ...,
       [0.2997154 , 0.16323296, 1.        , ..., 0.51328817, 0.46556122,
        0.30047506],
       [0.12860192, 0.16006339, 0.66666667, ..., 0.53673788, 0.4375    ,
        0.12767221],
       [0.1638207 , 0.09825674, 1.        , ..., 0.54637832, 0.47321429,
        0.13776722]])
In [88]:
y2_train
Out[88]:
array([[0.28442728],
       [0.2046332 ],
       [0.34877735],
       ...,
       [0.26640927],
       [0.28700129],
       [0.34877735]])
In [89]:
y2_test
Out[89]:
array([[0.26933333],
       [0.336     ],
       [0.23733333],
       ...,
       [0.28266667],
       [0.25066667],
       [0.26666667]])

Antwort:

  • Man will in jeder Partition (Training und Test) jeweils eine Skala von 0 bis 1 haben
  • Wenn man vor der Partition skalieren würde, könnte man nicht garantieren, dass beide Partitionen eine Skala von 0 bis 1 haben

Training, Test und Evaluation verschiedener Regressionsmodelle¶

Führen Sie die folgenden Teilaufgaben sowohl für ein Single Layer Perceptron als auch für ein Multi Layer Perceptron mit 20 Neuronen in der Hidden-Schicht durch. Vergleichen Sie am Ende die Performance der beiden Verfahren.

In [90]:
def determineRegressionMetrics(y_test,y_pred,title=""):
    mse = mean_squared_error(y_test, y_pred)
    mad = mean_absolute_error(y_test, y_pred)
    rmsle=np.sqrt(mean_squared_error(np.log(y_test+1),np.log(y_pred+1)))# +1 for avoiding log(0) 
    r2=r2_score(y_test, y_pred)
    med=median_absolute_error(y_test, y_pred)
    print(title)
    print("Mean absolute error =", round(mad, 2))
    print("Mean squared error =", round(mse, 2))
    print("Median absolute error =", round(med, 2))
    print("R2 score =", round(r2, 2))
    print("Root Mean Squared Logarithmic Error =",rmsle)

Single Layer Perceptron¶

  1. Trainieren Sie den Algorithmus mit den Trainingsdaten.
In [91]:
reg_sl = SGDRegressor(random_state=42)
reg_sl.fit(X2_train, y2_train)
C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\utils\validation.py:1184: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

Out[91]:
SGDRegressor(random_state=42)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
SGDRegressor(random_state=42)
  1. Wenden Sie das gelernte Modell auf die Testdaten an.
In [92]:
reg_sl.predict(X2_test)
Out[92]:
array([0.35401494, 0.3427621 , 0.33877106, ..., 0.3649114 , 0.32096766,
       0.31535955])

Multilayer Perceptron¶

  1. Trainieren Sie den Algorithmus mit den Trainingsdaten.
  2. Wenden Sie das gelernte Modell auf die Testdaten an.
In [93]:
reg_ml = MLPRegressor(random_state=42, hidden_layer_sizes=20)
reg_ml.fit(X2_train, y2_train)
C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

Out[93]:
MLPRegressor(hidden_layer_sizes=20, random_state=42)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
MLPRegressor(hidden_layer_sizes=20, random_state=42)
In [94]:
reg_ml.predict(X2_test)
Out[94]:
array([0.24598485, 0.25035327, 0.29124764, ..., 0.31398969, 0.21079277,
       0.19297961])

Vergleich¶

  1. Evaluieren Sie die Qualität der Modelle, indem Sie auf die vorhergesagten Ausgaben und die wahren Ausgaben die unten gegebene Funktion aufrufen.
In [95]:
single_metrics = determineRegressionMetrics(y_test=y2_test, y_pred=reg_sl.predict(X2_test))
Mean absolute error = 0.05
Mean squared error = 0.01
Median absolute error = 0.05
R2 score = 0.28
Root Mean Squared Logarithmic Error = 0.05707240761003042
In [96]:
multi_metrics = determineRegressionMetrics(y_test=y2_test, y_pred=reg_ml.predict(X2_test))
Mean absolute error = 0.06
Mean squared error = 0.01
Median absolute error = 0.05
R2 score = 0.22
Root Mean Squared Logarithmic Error = 0.05935435700780056

Antwort:

  • Die Modelle liefern sehr geringe Fehlerwerte und somit einen sehr guten Wert bei der Predictoin
  • Die Ergebnisse der verschiedenen Metriken weichen nur minimal voneinander ab. Somit liefern die beiden Ansätze (Single Layer Perceptron und Multi Layer Perceptron) die gleichen Ergebnisse
  1. Beschreiben Sie kurz die in der Funktion verwendeten Metriken

Mean Absolute Error: It measures the average absolute difference between the predicted values and the actual target values
Mean Squared Error: It calculates the average of the squares of the errors
Median Absolute Error: It calculates the median between the predicted values and the actual target values
R2 Score: R² kann zwischen 0 un 1 liegen. Es erklärt wie gut ein Modell die Varianz der abhängigen Variablen erklärt.
Root Mean Squared Logarithmis Error: It calculates the average of the squares of the errors, but focuse more on the error count and less on the values of the erros

Hyperparameteroptimierung¶

Für ein Multi Layer Perceptron soll eine Hyperparameteroptimierung durchgeführt werden. Ziel ist es innerhalb der unten vorgegebenen Wertebereiche für die Hyperparameter hidden_layer_sizes, activation und learning_rate die beste Konfiguration zu finden. Hierzu kann entweder GridSearchCV oder RandomizedSearchCV eingesetzt werden. GridSearchCV testet einfach alle Konfigurationen durch, benötigt daher aber viel Zeit. RandomizedSearchCV geht heuristisch und damit schneller durch den Suchraum. Wenden Sie eines dieser beiden Verfahren an, um für das unten gegebene Parameter-Grid die optimale Konfiguration zu finden. Welches ist die optimale Konfiguration und zu welchem neg_mean_absolute_error führt diese wenn man das scoring argument der Funktion entsprechend einstellt?

In [97]:
regr = MLPRegressor(random_state=42)
In [98]:
param_grid = [{'hidden_layer_sizes': [(10,),(20,),(30,),(40,),(50,),(100,),(10,10)], 
               'activation': ["logistic", "tanh", "relu"], 
               'learning_rate': ["constant", "invscaling", "adaptive"]}]
In [99]:
rs_m = RandomizedSearchCV(regr, param_distributions=param_grid, scoring='neg_mean_absolute_error')
In [100]:
# Die Fehlermeldungen bitte ignorieren
rs_m.fit(X2_train, y2_train)
C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\neural_network\_multilayer_perceptron.py:1625: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

Out[100]:
RandomizedSearchCV(estimator=MLPRegressor(random_state=42),
                   param_distributions=[{'activation': ['logistic', 'tanh',
                                                        'relu'],
                                         'hidden_layer_sizes': [(10,), (20,),
                                                                (30,), (40,),
                                                                (50,), (100,),
                                                                (10, 10)],
                                         'learning_rate': ['constant',
                                                           'invscaling',
                                                           'adaptive']}],
                   scoring='neg_mean_absolute_error')
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
RandomizedSearchCV(estimator=MLPRegressor(random_state=42),
                   param_distributions=[{'activation': ['logistic', 'tanh',
                                                        'relu'],
                                         'hidden_layer_sizes': [(10,), (20,),
                                                                (30,), (40,),
                                                                (50,), (100,),
                                                                (10, 10)],
                                         'learning_rate': ['constant',
                                                           'invscaling',
                                                           'adaptive']}],
                   scoring='neg_mean_absolute_error')
MLPRegressor(random_state=42)
MLPRegressor(random_state=42)
In [101]:
rs_m.best_params_
Out[101]:
{'learning_rate': 'invscaling',
 'hidden_layer_sizes': (100,),
 'activation': 'relu'}
In [102]:
rs_m.best_score_
Out[102]:
-0.03770788148445644

Antwort:
Beim neg_mean_absolute_error deutet ein Wert, der näher an Null liegt (also ein kleinerer negativer Wert), auf eine bessere Modellleistung hin.

Eigene Hypothese¶

Das Hinzufügen des Getriebetypes bei dem Singel Layer Percteptron führt zu besseren Ausgaben bei der Prediction der CO2-Emissionen.¶

  1. Data Selection and Encoding
In [103]:
co2_df_h = df[["Getriebeart", "CCM", "HST PS", "Anzahl der Türen", "Leergewicht", "Zuladung", "Länge", "Breite", "Höhe", "CO2-Emissionen"]]
In [104]:
lb.fit(co2_df_h['Getriebeart'])
co2_df_h['Getriebeart'] = lb.transform(co2_df_h['Getriebeart'])
C:\Users\paulv\AppData\Local\Temp\ipykernel_166776\1582940501.py:2: SettingWithCopyWarning:


A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy

In [105]:
co2_df_h
Out[105]:
Getriebeart CCM HST PS Anzahl der Türen Leergewicht Zuladung Länge Breite Höhe CO2-Emissionen
0 1 1896 154 4 2211 905 4852 1849 2019 218.0
1 1 1990 148 4 2243 753 4859 1827 1938 218.0
2 1 1943 150 4 2282 768 4788 1823 1990 218.0
3 1 2013 153 4 1954 1007 4927 1952 1935 210.0
4 1 1945 152 4 1984 972 4916 1872 2026 210.0
... ... ... ... ... ... ... ... ... ... ...
24189 0 2036 235 5 1755 798 4756 1911 1779 158.0
24190 0 1974 241 5 1770 775 4605 1977 1738 162.0
24191 0 2018 240 5 1763 804 5033 2011 1592 153.0
24192 0 1968 238 5 1704 820 4795 1941 1602 153.0
24193 0 2019 239 5 1769 821 5022 1865 1771 162.0

24194 rows × 10 columns

  1. Visuelle Korrelation
In [106]:
px.scatter(co2_df_h,
           x='Getriebeart', 
           y='CO2-Emissionen',
           title='Getriebeart im Vergleich zur CO2-Emissionen')
  1. Train Test Split
In [107]:
X_h = co2_df_h.iloc[:, :-1]
y_h = co2_df_h.iloc[:, -1:]
In [108]:
X_h_train, X_h_test, y_h_train, y_h_test = train_test_split(X_h, y_h, test_size=0.3, random_state=42)
  1. Data Scaling
In [109]:
scaler.fit(X_h_train)
X_h_train = scaler.transform(X_h_train)
In [110]:
scaler.fit(X_h_test)
X_h_test = scaler.transform(X_h_test)
In [111]:
scaler.fit(y_h_train)
y_h_train = scaler.transform(y_h_train)
In [112]:
scaler.fit(y_h_test)
y_h_test = scaler.transform(y_h_test)
  1. Training des Singel Layer Perceptron
In [113]:
reg_sl_h = SGDRegressor(random_state=42)
reg_sl_h.fit(X_h_train, y_h_train)
C:\Users\paulv\anaconda3\envs\DataMining\lib\site-packages\sklearn\utils\validation.py:1184: DataConversionWarning:

A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().

Out[113]:
SGDRegressor(random_state=42)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
SGDRegressor(random_state=42)
In [114]:
reg_sl_h.predict(X_h_test)
Out[114]:
array([0.35361514, 0.34203285, 0.33950959, ..., 0.36436785, 0.32152107,
       0.31572454])
In [115]:
single_metrics_h = determineRegressionMetrics(y_test=y_h_test, y_pred=reg_sl_h.predict(X_h_test))
Mean absolute error = 0.05
Mean squared error = 0.01
Median absolute error = 0.05
R2 score = 0.28
Root Mean Squared Logarithmic Error = 0.05704888332794298

Anwort:
Die Hypothese wurde widerlegt.
Das Hinzufügen des Getriebetyps zu den Daten für das Training des Single Layer Perceptrons verbesser NICHT die Ausgaben bei der Prediction der CO2-Emissionen. Tatsächlich steigt nur der Root Mean Squard Logarithmic Error um lediglich 0.00003, was keine Relevanz hat.
Damit tritt auch die Nullhypothese ein die besagt: "Das Hinzufügen des Getriebetypes bei dem Singel Layer Percteptron führt zu keiner Verbesserung der Ausgaben bei der Prediction der CO2-Emissionen."
Ein Hinweis auf das Endergebniss ergab sich bereits aus der visuellen Korrelationsanalyse, welche keine besonderen Korrelationen darstellte.